//
// Created by Ivor_ on 2023/11/28.
//

#include "randomBits.h"

unsigned long long int sRand_LCG(unsigned long long int newSeed) {
    seedForLCG = newSeed;
    for (int i = 0; i < 0x7ff; ++i) {
        rand_LCG();
    }
    return newSeed;
}

unsigned long long int rand_LCG() {
    const unsigned long long int a1 = 5761455llu, a2 = 455052511llu, a3 = 50847534llu;
    unsigned long long int next = (a1 * seedForLCG + a2) % a3;
    seedForLCG = next;
    return next;
}

double rand_LCGD() {
    return 1. * rand_LCG() / 50847535.0;
}

struct randomLCG rlcg(void) {
    struct randomLCG rl;
    rl.currentSeed = seedForLCG;
    rl.srand = sRand_LCG;
    rl.randi = rand_LCG;
    rl.randf = rand_LCGD;
    return rl;
}

unsigned long long int sRand_MWC(unsigned long long int newSeed) {
    seedForMWC = newSeed;
    for (int i = 0; i < 0x7ff; ++i) {
        rand_MWC();
    }
    return newSeed;
}

unsigned long long int rand_MWC() {
    static unsigned long long int a1 = 123456789llu, a2 = 362436069llu, a3 = 77465321llu;
    unsigned long long int temp = 916905990llu * a1 + seedForMWC;
    a1 = a2, seedForMWC = temp >> 32;
    a2 = a3;
    a3 = temp & 0xffffffffllu;
    return a3;
}

double rand_MWCD() {
    return 1. * rand_MWC() / (1llu << 32);
}

struct randomMWC rmwc(void) {
    struct randomMWC rm;
    rm.currentSeed = seedForMWC;
    rm.srand = sRand_MWC;
    rm.randi = rand_MWC;
    rm.randf = rand_MWCD;
    return rm;
}

unsigned long long int sRand_XorShift(unsigned long long int newSeed) {
    seedForMWC ^= newSeed;
    for (int i = 0; i < 0x7ff; ++i) {
        rand_MWC();
    }
    return newSeed;
}

unsigned long long int rand_XorShift() {
    static unsigned long long int a1 = 123456789llu, a2 = 362436069llu, a3 = 521288629llu;
    unsigned long long int temp = a1 ^ (a1 << 11);
    a1 = a2;
    a2 = a3;
    a3 = seedForXorShift;
    seedForXorShift = seedForXorShift ^ (seedForXorShift >> 19) ^ (temp ^ (temp >> 8));
    return seedForXorShift & 0xffffffff;
}

double rand_XorShiftD() {
    return 1. * rand_XorShift() / 4294967296.0;
}

struct randomXorShift rXorS(void) {
    struct randomXorShift rxs;
    rxs.currentSeed = seedForXorShift;
    rxs.srand = sRand_XorShift;
    rxs.randi = rand_XorShift;
    rxs.randf = rand_XorShiftD;
    return rxs;
}
